#include "set.h"

#include "mem.h"

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

static void
test()
{
    Set_T set = Set_new(1000, NULL, NULL);

    assert(Set_length(set) == 0);
    assert(Set_member(set, "hello") == 0);

    Set_put(set, "hello");
    assert(Set_member(set, "hello") == 1);
    assert(Set_length(set) == 1);

    Set_remove(set, "hello");
    assert(Set_member(set, "hello") == 0);
    assert(Set_length(set) == 0);

    Set_free(&set);
    assert(set == NULL);
}

static void
free_node(const void *member, void *cl)
{
    (void)cl;
    free((void*)member);
}

static void
test_update()
{
    Set_T set = Set_new(1000, NULL, NULL);
    Set_put(set, "hello");
    Set_put(set, "how");
    Set_put(set, "are");
    Set_put(set, "you");
    Set_put(set, "hello");
    assert(Set_length(set) == 4);

    assert(Set_member(set, "hello") == 1);
    Set_remove(set, "hello");
    assert(Set_length(set) == 3);
    assert(Set_member(set, "hello") == 0);

    void **arr = Set_toArray(set, NULL);
    for (int i = 0; arr[i]; i++)
        assert(Set_member(set, arr[i]) == 1);
    FREE(arr);
    Set_free(&set);

    set = Set_new(1000, NULL, NULL);
    Set_put(set, malloc(sizeof(int)));
    Set_put(set, malloc(sizeof(int)));
    Set_put(set, malloc(sizeof(int)));
    Set_map(set, free_node, NULL);
    Set_free(&set);
}

static void
equal_set(Set_T s, Set_T t)
{
    void **arr = Set_toArray(s, NULL);
    for (int i = 0; arr[i]; i++)
        assert(Set_member(t, arr[i]) == 1);
    FREE(arr);

    arr = Set_toArray(t, NULL);
    for (int i = 0; arr[i]; i++)
        assert(Set_member(s, arr[i]) == 1);
    FREE(arr);

    assert(Set_length(s));
    assert(Set_length(t));
}

static void
equal_set2(Set_T set, char **arr)
{
    int i;
    for (i = 0; arr[i]; i++)
        assert(Set_member(set, arr[i]) == 1);
}

static void
test_set_oper()
{
    Set_T set = Set_new(1000, NULL, NULL);
    Set_put(set, "hello");
    Set_put(set, "how");
    Set_put(set, "are");
    Set_put(set, "you");

    Set_T set2 = Set_new(1000, NULL, NULL); 
    Set_put(set2, "are");
    Set_put(set2, "you");
    Set_put(set2, "ok");
    Set_put(set2, "now");


    Set_T tmp = Set_union(set, NULL);
    equal_set(set, tmp);
    Set_free(&tmp);

    tmp = Set_union(NULL, set2);
    equal_set(set2, tmp);
    Set_free(&tmp);

    char *strs[] = {"hello", "how", "are", "you", "ok", "now", NULL};
    tmp = Set_union(set, set2);
    assert(Set_length(tmp) == 6);
    equal_set2(tmp, strs);
    Set_free(&tmp);


    tmp = Set_inter(set, NULL);
    assert(Set_length(tmp) == 0);
    Set_free(&tmp);

    tmp = Set_inter(NULL, set2);
    assert(Set_length(tmp) == 0);
    Set_free(&tmp);

    char *strs2[] = {"are", "you", NULL};
    tmp = Set_inter(set, set2);
    assert(Set_length(tmp) == 2);
    equal_set2(tmp, strs2);
    Set_free(&tmp);


    tmp = Set_minus(set, NULL);
    equal_set(set, tmp);
    Set_free(&tmp);

    tmp = Set_minus(NULL, set2);
    assert(Set_length(tmp) == 0);
    Set_free(&tmp);

    char *strs3[] = {"hello", "how", NULL};
    tmp = Set_minus(set, set2);
    assert(Set_length(tmp) == 2);
    equal_set2(tmp, strs3);
    Set_free(&tmp);


    tmp = Set_diff(set, NULL);
    equal_set(set, tmp);
    Set_free(&tmp);

    tmp = Set_diff(NULL, set2);
    equal_set(set2, tmp);
    Set_free(&tmp);

    char *strs4[] = {"hello", "how", "ok", "now", NULL};
    tmp = Set_diff(set, set2);
    assert(Set_length(tmp) == 4);
    equal_set2(tmp, strs4);
    Set_free(&tmp);


    Set_free(&set);
    Set_free(&set2);
}

int main()
{
    test();
    test_update();
    test_set_oper();
    return 0;
}

